package service

import (
	"bloggo/bloggo"
	"bloggo/structs"
	"context"
	"errors"
	"fmt"
	"gitee.com/chunanyong/logger"
	"gitee.com/chunanyong/zorm"
	"strconv"
)

//SaveTbArticleTagStruct 保存
//如果入参ctx中没有dbConnection,使用defaultDao开启事务并最后提交
//如果入参ctx有dbConnection且没有事务,调用dbConnection.begin()开启事务并最后提交
//如果入参ctx有dbConnection且有事务,只使用不提交,有开启方提交事务
//但是如果遇到错误或者异常,虽然不是事务的开启方,也会回滚事务,让事务尽早回滚
func SaveTbArticleTagStruct(ctx context.Context, tbarticletagstruct *structs.TbArticleTagStruct) error {

	// tbarticletagstruct对象指针不能为空
	if tbarticletagstruct == nil {
		return errors.New("tbarticletagstruct对象指针不能为空")
	}
	//匿名函数return的error如果不为nil,事务就会回滚
	_, errSaveTbArticleTagStruct := zorm.Transaction(ctx, func(ctx context.Context) (interface{}, error) {

		//事务下的业务代码开始

		_, errSaveTbArticleTagStruct := zorm.Insert(ctx, tbarticletagstruct)

		if errSaveTbArticleTagStruct != nil {
			return nil, errSaveTbArticleTagStruct
		}

		return nil, nil
		//事务下的业务代码结束

	})

	//记录错误
	if errSaveTbArticleTagStruct != nil {
		errSaveTbArticleTagStruct := fmt.Errorf("service.SaveTbArticleTagStruct错误:%w", errSaveTbArticleTagStruct)
		logger.Error(errSaveTbArticleTagStruct)
		return errSaveTbArticleTagStruct
	}

	return nil
}

//UpdateTbArticleTagStruct 更新
//如果入参ctx中没有dbConnection,使用defaultDao开启事务并最后提交
//如果入参ctx有dbConnection且没有事务,调用dbConnection.begin()开启事务并最后提交
//如果入参ctx有dbConnection且有事务,只使用不提交,有开启方提交事务
//但是如果遇到错误或者异常,虽然不是事务的开启方,也会回滚事务,让事务尽早回滚
func UpdateTbArticleTagStruct(ctx context.Context, tbarticletagstruct *structs.TbArticleTagStruct) error {

	// tbarticletagstruct对象指针或主键Id不能为空
	if tbarticletagstruct == nil || tbarticletagstruct.Id < 1 {
		return errors.New("tbarticletagstruct对象指针或主键Id不能为空")
	}

	//匿名函数return的error如果不为nil,事务就会回滚
	_, errUpdateTbArticleTagStruct := zorm.Transaction(ctx, func(ctx context.Context) (interface{}, error) {

		//事务下的业务代码开始
		_, errUpdateTbArticleTagStruct := zorm.Update(ctx, tbarticletagstruct)

		if errUpdateTbArticleTagStruct != nil {
			return nil, errUpdateTbArticleTagStruct
		}

		return nil, nil
		//事务下的业务代码结束

	})

	//记录错误
	if errUpdateTbArticleTagStruct != nil {
		errUpdateTbArticleTagStruct := fmt.Errorf("service.UpdateTbArticleTagStruct错误:%w", errUpdateTbArticleTagStruct)
		logger.Error(errUpdateTbArticleTagStruct)
		return errUpdateTbArticleTagStruct
	}

	return nil
}

//UpdateNotZeroTbArticleTagStruct 更新
//如果入参ctx中没有dbConnection,使用defaultDao开启事务并最后提交
//如果入参ctx有dbConnection且没有事务,调用dbConnection.begin()开启事务并最后提交
//如果入参ctx有dbConnection且有事务,只使用不提交,有开启方提交事务
//但是如果遇到错误或者异常,虽然不是事务的开启方,也会回滚事务,让事务尽早回滚
func UpdateNotZeroTbArticleTagStruct(ctx context.Context, tbarticletagstruct *structs.TbArticleTagStruct) error {

	// tbarticletagstruct对象指针或主键Id不能为空
	if tbarticletagstruct == nil || tbarticletagstruct.Id < 1 {
		return errors.New("tbarticletagstruct对象指针或主键Id不能为空")
	}

	//匿名函数return的error如果不为nil,事务就会回滚
	_, errUpdateTbArticleTagStruct := zorm.Transaction(ctx, func(ctx context.Context) (interface{}, error) {

		//事务下的业务代码开始
		_, errUpdateTbArticleTagStruct := zorm.UpdateNotZeroValue(ctx, tbarticletagstruct)

		if errUpdateTbArticleTagStruct != nil {
			return nil, errUpdateTbArticleTagStruct
		}

		return nil, nil
		//事务下的业务代码结束

	})

	//记录错误
	if errUpdateTbArticleTagStruct != nil {
		errUpdateTbArticleTagStruct := fmt.Errorf("service.UpdateNotZeroTbArticleTagStruct错误:%w", errUpdateTbArticleTagStruct)
		logger.Error(errUpdateTbArticleTagStruct)
		return errUpdateTbArticleTagStruct
	}

	return nil
}

//DeleteTbArticleTagStructById 根据Id删除
//如果入参ctx中没有dbConnection,使用defaultDao开启事务并最后提交
//如果入参ctx有dbConnection且没有事务,调用dbConnection.begin()开启事务并最后提交
//如果入参ctx有dbConnection且有事务,只使用不提交,有开启方提交事务
//但是如果遇到错误或者异常,虽然不是事务的开启方,也会回滚事务,让事务尽早回滚
func DeleteTbArticleTagStructById(ctx context.Context, id string) error {

	//id不能为空
	if len(id) < 1 {
		return errors.New("id不能为空")
	}

	//匿名函数return的error如果不为nil,事务就会回滚
	_, errDeleteTbArticleTagStruct := zorm.Transaction(ctx, func(ctx context.Context) (interface{}, error) {

		//事务下的业务代码开始
		finder := zorm.NewDeleteFinder(structs.TbArticleTagStructTableName).Append(" WHERE id=?", id)
		_, errDeleteTbArticleTagStruct := zorm.UpdateFinder(ctx, finder)

		if errDeleteTbArticleTagStruct != nil {
			return nil, errDeleteTbArticleTagStruct
		}

		return nil, nil
		//事务下的业务代码结束

	})

	//记录错误
	if errDeleteTbArticleTagStruct != nil {
		errDeleteTbArticleTagStruct := fmt.Errorf("service.DeleteTbArticleTagStruct错误:%w", errDeleteTbArticleTagStruct)
		logger.Error(errDeleteTbArticleTagStruct)
		return errDeleteTbArticleTagStruct
	}

	return nil
}

//FindTbArticleTagStructById 根据Id查询信息
//ctx中如果没有dbConnection,则会使用默认的datasource进行无事务查询
func FindTbArticleTagStructById(ctx context.Context, id string) (*structs.TbArticleTagStruct, error) {
	//id不能为空
	if len(id) < 1 {
		return nil, errors.New("id不能为空")
	}

	//根据Id查询
	finder := zorm.NewSelectFinder(structs.TbArticleTagStructTableName).Append(" WHERE id=?", id)
	tbarticletagstruct := structs.TbArticleTagStruct{}
	has, errFindTbArticleTagStructById := zorm.QueryRow(ctx, finder, &tbarticletagstruct)

	//记录错误
	if errFindTbArticleTagStructById != nil {
		errFindTbArticleTagStructById := fmt.Errorf("service.FindTbArticleTagStructById错误:%w", errFindTbArticleTagStructById)
		logger.Error(errFindTbArticleTagStructById)
		return nil, errFindTbArticleTagStructById
	}

	if !has {
		return nil, nil
	}

	return &tbarticletagstruct, nil

}

//FindTbArticleTagStructList 根据Finder查询列表
//ctx中如果没有dbConnection,则会使用默认的datasource进行无事务查询
func FindTbArticleTagStructList(ctx context.Context, finder *zorm.Finder, page *zorm.Page) ([]structs.TbArticleTagStruct, error) {

	//finder不能为空
	if finder == nil {
		return nil, errors.New("finder不能为空")
	}

	tbarticletagstructList := make([]structs.TbArticleTagStruct, 0)
	errFindTbArticleTagStructList := zorm.Query(ctx, finder, &tbarticletagstructList, page)

	//记录错误
	if errFindTbArticleTagStructList != nil {
		errFindTbArticleTagStructList := fmt.Errorf("service.FindTbArticleTagStructList错误:%w", errFindTbArticleTagStructList)
		logger.Error(errFindTbArticleTagStructList)
		return nil, errFindTbArticleTagStructList
	}

	return tbarticletagstructList, nil
}

func RemoveTagsByArticleId(articleId string) (bool, error) {
	//匿名函数return的error如果不为nil,事务就会回滚
	_, err := zorm.Transaction(context.Background(), func(ctx context.Context) (interface{}, error) {
		//事务下的业务代码开始
		finder := zorm.NewDeleteFinder(structs.TbArticleTagStructTableName).Append("WHERE article_id = ?", articleId)
		_, err := zorm.UpdateFinder(ctx, finder)
		if err != nil {
			return nil, err
		}
		return nil, nil
		//事务下的业务代码结束
	})
	if err != nil {
		bloggo.Log(err.Error())
		return false, err
	}
	return true, nil
}

func SaveArticleTags(articleId string, tagIds []int) error {
	if len(articleId) == 0 || len(tagIds) == 0 {
		return errors.New("args is empty")
	}
	_, err := zorm.Transaction(context.Background(), func(ctx context.Context) (interface{}, error) {
		for _, v := range tagIds {
			var at structs.TbArticleTagStruct
			at.ArticleId, _ = strconv.Atoi(articleId)
			at.TagId = v
			_, err := zorm.Insert(ctx, &at)
			if err != nil {
				return nil, err
			}
		}
		return nil, nil
	})
	return err
}
